package com.hook.tools;

import android.content.Context;
import android.util.Log;

import com.hook.http.HttpServer;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;


import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

import static de.robv.android.xposed.XposedBridge.log;

public class initXposedHook implements IXposedHookLoadPackage {
    public static ClassLoader classLoader = null;
    //美团
    public static Object meituanApiClassObject = null;
    public static Object meituanSCApiClassObject = null;
    public static Object rx_jObject = null;

    public static Method postFormRequestMethod = null;
    public static Object postFormRequestObject = null;
    //每日优鲜
    public static Context meiriyouxianContext = null;
    public static Class<?> meiriyouxinSecurityClass = null;

    //web服务启动端口
    static HttpServer meituanServer = new HttpServer(2222);
    static HttpServer meiriyouxianServer = new HttpServer(3333);

    @Override
    public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        Log.e("EDXposed",loadPackageParam.packageName);
        if(loadPackageParam.packageName.equals("com.sankuai.meituan") && loadPackageParam.processName.equals("com.sankuai.meituan")){
            classLoader = loadPackageParam.classLoader;
//            Class<?> cls = XposedHelpers.findClass("com.meituan.android.mrn.network.b",loadPackageParam.classLoader);
//            postFormRequestMethod = cls.getDeclaredMethod("postFormRequest",Map.class,String.class,Map.class,Map.class);

            XposedHelpers.findAndHookMethod("com.sankuai.meituan.retrofit2.ClientCall", loadPackageParam.classLoader,
                    "getResponseWithInterceptorChain",
                    XposedHelpers.findClass("com.sankuai.meituan.retrofit2.Request",loadPackageParam.classLoader)
                    ,new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param);
                            if (!meituanServer.isAlive()){
                                meituanServer.start();
                                if (meituanServer.isAlive()){
                                    Log.e("EDXposed","服务启动成功,端口号为:2222");
//                                    Class<?> clazz = XposedHelpers.findClass("com.sankuai.waimai.platform.capacity.network.retrofit.b",loadPackageParam.classLoader);
//                                    Class<?> apiClass = XposedHelpers.findClass("com.sankuai.waimai.business.page.home.model.API",loadPackageParam.classLoader);
//                                    meituanApiClassObject = XposedHelpers.callMethod(clazz.newInstance(),"create",apiClass);
//                                    Log.e("EDXposed","API实现类对象" + meituanApiClassObject.getClass().getName());
//                                    for (Method m :meituanApiClassObject.getClass().getDeclaredMethods()){
//                                        Log.e("EDXposed",m.getName());
//                                    }
//                                    Class<?> scApiClass = XposedHelpers.findClass("com.sankuai.waimai.store.base.net.sg.SCApiService",loadPackageParam.classLoader);
//                                    meituanSCApiClassObject = XposedHelpers.callMethod(clazz.newInstance(),"create",scApiClass);
//                                    for (Method m :meituanSCApiClassObject.getClass().getDeclaredMethods()){
//                                        Log.e("EDXposed",m.getName());
//                                    }
                                }else{
                                    Log.e("EDXposed","服务启动失败,原因未知.");
                                }
                            }else{
//                                Log.e("EDXposed","服务已经启动");
                            }
                        }
                        @Override
                        protected synchronized void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            //首先获取请求的url地址
                            Object requestObject = param.args[0];
                            Method requestMethod = requestObject.getClass().getDeclaredMethod("url");
                            requestMethod.setAccessible(true);
                            String requestUrl = requestMethod.invoke(requestObject).toString();
                            requestMethod = requestObject.getClass().getDeclaredMethod("method");
                            requestMethod.setAccessible(true);
                            String method = requestMethod.invoke(requestObject).toString();
//                            Log.e("EDXposed","请求方法" + method + " 请求地址为:"+requestUrl);
                            //继续下一步通过反射拿到返回数据
                            Object rawResponse = param.getResult();
                            if (rawResponse != null) {
                                Method mbody = rawResponse.getClass().getDeclaredMethod("body");
                                rawResponse = mbody.invoke(rawResponse);
//                            Log.e("EDXposed",rawResponse.getClass().getName());
                                if (rawResponse.getClass().getName().equals("com.sankuai.meituan.retrofit2.ResponseBodySubject") && method.equals("POST")) {
                                    // 处理返回对象数据
                                    Method sourceMethod = rawResponse.getClass().getDeclaredMethod("source");
                                    InputStream is = (InputStream) sourceMethod.invoke(rawResponse);
                                    //copy inputStream
                                    ByteArrayOutputStream baos = IOUtils.inputConvertByteArray(is);
                                    is = IOUtils.byteArrayConvertInputStream(baos);
                                    String str = IOUtils.readStreamToString(is);
                                    is = IOUtils.byteArrayConvertInputStream(baos);
                                    //回写流操作,否则APP无法拿到数据进行展示
                                    //首先通过反射构造InputStreamSubject对象
                                    Class<?> inputSubject = XposedHelpers.findClass("com.sankuai.meituan.retrofit2.InputStreamSubject", loadPackageParam.classLoader);
                                    Constructor<?> inputSubjectConst = inputSubject.getConstructor(InputStream.class);
                                    Object inputSubjectObject = inputSubjectConst.newInstance(is);
                                    //构造对象写回数据
                                    Field subject = rawResponse.getClass().getDeclaredField("inputStreamSubject");
                                    subject.setAccessible(true);
                                    subject.set(rawResponse, inputSubjectObject);
                                    baos.close();
                                    if (MyThreadLocal.getInstance().get() != null){
                                        MyThreadLocal.getInstance().set(str);
                                    }
                                }
                            }
                        }
                    });

            //            保存rd.j对象
            XposedHelpers.findAndHookMethod("com.sankuai.waimai.platform.capacity.network.retrofit.b",
                    loadPackageParam.classLoader,
                    "a",
                    XposedHelpers.findClass("rx.d", loadPackageParam.classLoader),
                    XposedHelpers.findClass("rx.j", loadPackageParam.classLoader),
                    Object.class,
                    new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            rx_jObject = param.args[1];
                        }
                    }
            );
            XposedHelpers.findAndHookMethod("com.sankuai.waimai.platform.capacity.network.retrofit.b",
                    loadPackageParam.classLoader,
                    "a",
                    Class.class,
                    new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            if (param.args[0].toString().contains("com.sankuai.waimai.business.page.home.model.API")){
                                //保存接口实现对象...
                                Log.e("EDXposed","已获得 ApiService 对象的实现类对象");
                                meituanApiClassObject = param.getResult();
                            }
                        }
                    });
            XposedHelpers.findAndHookMethod("com.sankuai.waimai.store.base.net.sg.a",
                    loadPackageParam.classLoader,
                    "a",
                    Object.class,
                    new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            Log.e("EDXposed",param.args[0].toString());
                            if (param.args[0].toString().contains("PoiVerticalityHomeActivity")) {
                                Log.e("EDXposed", "已获得 SCApiService 对象的实现类对象");
                                Object resObj = param.getResult();
                                Field f = resObj.getClass().getField("b");
                                resObj = f.get(resObj);
                                Log.e("EDXposed",resObj.getClass().getName());
                                for (Method m : resObj.getClass().getDeclaredMethods()){
                                    Log.e("EDXposed",m.getName());
                                }
                                meituanSCApiClassObject = resObj;
//                                XposedHelpers.findAndHookMethod(meituanSCApiClassObject.getClass().getName(),
//                                        loadPackageParam.classLoader,
//                                        "getProducts",
//                                        int.class,
//                                        String.class,
//                                        String.class,
//                                        int.class,
//                                        int.class,
//                                        int.class,
//                                        long.class,
//                                        String.class,
//                                        String.class,
//                                        String.class,
//                                        new XC_MethodHook() {
//                                            @Override
//                                            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
//                                                super.beforeHookedMethod(param);
//                                                for (int i = 0; i < param.args.length; i++)
//                                                    Log.e("EDXposed","参数"+(i+1)+":"+(param.args[i]==null?"null":param.args[i].toString()));
//                                            }
//                                        });
                            }

                        }
                    });

            //获得搜索类对象
            XposedHelpers.findAndHookMethod("com.meituan.android.mrn.network.b",
                    loadPackageParam.classLoader,
                    "a",
                    Context.class,
                    String.class,
                    List.class,new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param);
                            postFormRequestObject = param.getResult();
                            Log.e("EDXposed","已获得搜索 接口类对象....");
                        }
                    });
        }
        else if(loadPackageParam.packageName.equals("cn.missfresh.application") && loadPackageParam.processName.equals("cn.missfresh.application")){
            XposedHelpers.findAndHookMethod("com.secneo.apkwrapper.AW", loadPackageParam.classLoader, "attachBaseContext",
                    Context.class, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            super.beforeHookedMethod(param);
                            final Context context = (Context)param.args[0];
                            XposedHelpers.findAndHookMethod("cn.missfresh.wsg.SecurityLib", context.getClassLoader(), "a",
                                    Context.class, byte[].class, new XC_MethodHook() {
                                        @Override
                                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                                            super.beforeHookedMethod(param);
                                            if (!meiriyouxianServer.isAlive()){
                                                meiriyouxianServer.start();
                                                Log.e("EDXposed","每日优鲜web服务开启结果: " + meiriyouxianServer.isAlive());
                                            }else{
                                                Log.e("EDXposed","每日优鲜web服务已启动");
                                            }
                                        }

                                        @Override
                                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                                            super.afterHookedMethod(param);
                                            meiriyouxinSecurityClass = XposedHelpers.findClass("cn.missfresh.wsg.SecurityLib",context.getClassLoader());
                                            meiriyouxianContext = (Context)param.args[0];
                                            String res = param.getResult().toString();
                                            Log.e("EDXposed","每日优鲜传入待加密数据为: " + new String((byte[])param.args[1]));
                                            Log.e("EDXposed","每日优鲜加密返回结果: " + res);
                                        }
                                    });
                        }

                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                        }
                    });
        }
    }
}
